﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using JigLibX.Math;
using JigLibX.Physics;
using JigLibX.Geometry;
using JigLibX.Collision;

using ProceduralGolf.geometry;

namespace ProceduralGolf.physics
{
    class CylinderObject : PhysicsObject
    {
        CylinderPrimitive primitive;
        Matrix rotation = Matrix.CreateRotationX(MathHelper.PiOver2);

        public CylinderObject(Game game, Vector3 position, float radius, float length)
            : base(position, new Vector3(radius, radius, length * 0.5f))
        {
            skin = new CollisionSkin(body);
            body = new Body();

            if (length - 2.0f * radius < 0.0f)
                throw new ArgumentException("Radius must be at least half length");

            Capsule middle = new Capsule(Vector3.Zero, Matrix.Identity, radius, length - 2.0f * radius);

            float sideLength = 2.0f * radius / (float)Math.Sqrt(2.0d);

            Vector3 sides = new Vector3(-0.5f * sideLength, -0.5f * sideLength, -radius);

            //Box supply0 = new Box(sides, Matrix.Identity,
            //    new Vector3(sideLength, sideLength, length));

            //Box supply1 = new Box(Vector3.Transform(sides, Matrix.CreateRotationZ(MathHelper.PiOver4)),
            //    Matrix.CreateRotationZ(MathHelper.PiOver4), new Vector3(sideLength, sideLength, length));

            skin.AddPrimitive(middle, new MaterialProperties(0.8f, 0.8f, 0.7f));
 //           skin.AddPrimitive(supply0, new MaterialProperties(0.8f, 0.8f, 0.7f));
 //           skin.AddPrimitive(supply1, new MaterialProperties(0.8f, 0.8f, 0.7f));

            body.CollisionSkin = this.skin;

            Vector3 com = SetMass(1.0f);
            skin.ApplyLocalTransform(new Transform(-com, Matrix.Identity));

            #region Manually set body inertia
            float cylinderMass = body.Mass;

            float comOffs = (length - 2.0f * radius) * 0.5f; ;

            float Ixx = 0.5f * cylinderMass * radius * radius + cylinderMass * comOffs * comOffs;
            float Iyy = 0.25f * cylinderMass * radius * radius + (1.0f / 12.0f) * cylinderMass * length * length + cylinderMass * comOffs * comOffs;
            float Izz = Iyy;

            body.SetBodyInertia(Ixx, Iyy, Izz);
            #endregion

            body.MoveTo(position, rotation);
            //body.MoveTo(position, Matrix.Identity);
            body.EnableBody();
            primitive = new CylinderPrimitive(game.GraphicsDevice, length, radius, 10);
        }

        ~CylinderObject()
        {
            primitive.Dispose();
        }

        public void Draw(Matrix world, Matrix view, Matrix projection, Color color)
        {
            Matrix myWorld = world * rotation * GetWorldMatrix();
            primitive.Draw(myWorld, view, projection, color);
        }
    }
}